package cn.hpb.serialportlibrary;


import android.app.Activity;
import android.content.Context;
import android.os.Process;
import android.util.Log;
import android.widget.Toast;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.taobao.weex.WXSDKEngine;
import com.taobao.weex.annotation.JSMethod;
import com.taobao.weex.bridge.JSCallback;
import com.taobao.weex.utils.WXLogUtils;


import java.io.File;

import android_serialport_api.SerialPortHelper;
import android_serialport_api.listener.IOpenSerialPortListener;
import android_serialport_api.listener.ISerialPortDataListener;
import android_serialport_api.listener.Status;
import cn.hpb.serialportlibrary.utils.ChangeTool;

/**
 * Version 1.0.5
 * 修复open回调bug
 * Version 1.0.6
 * 优化回调  分离发送接收方法
 * Version 1.0.7
 * 新增持续回调 新增移除回调
 * Version 1.0.9
 * 新增流控 解决回调闪退 新增流控
 */
public class serialport extends WXSDKEngine.DestroyableModule {

    private int flag;
    private JSONArray mArray;
    private Context mContext;
    private SerialPortHelper helper;
    private JSONObject mOption;
    private JSCallback mCallback;
    private ISerialPortDataListener sendListener;
    private final String TAG = serialport.class.getName();


    /**
     * 打开串口
     * @param option 参数
     * @param callback 是否打开成功回调
     */
    @JSMethod(uiThread = false)
    public void open(JSONObject option, final JSCallback callback){
        if(mWXSDKInstance.getContext() instanceof Activity){
            try{
                Log.e(TAG, "进入open");
                this.mOption = option;
                WXLogUtils.e("open==========================");
                mContext = mWXSDKInstance.getContext();
                if(helper == null){
                    helper = new SerialPortHelper();
                    String path = option.getString("path");
                    helper.setPort(path);
                    int baudRate = option.getIntValue("baudRate");
                    if(baudRate != 0){
                        helper.setBaudRate(baudRate);
                    }
                    int parity = option.getIntValue("parity");
                    if(parity != 0){
                        helper.setParity(parity);
                    }
                    int dataBits = option.getIntValue("dataBits");
                    if(dataBits != 0){
                        helper.setDataBits(dataBits);
                    }
                    int stopBit = option.getIntValue("stopBit");
                    if(stopBit != 0){
                        helper.setStopBits(stopBit);
                    }
                    int flowCon = option.getIntValue("flowCon");
                    if(flowCon != 0){
                        helper.setFlowCon(flowCon);
                    }
                }
                helper.setIOpenSerialPortListener(new IOpenSerialPortListener() {
                    @Override
                    public void onSuccess(final File device) {
                        WXLogUtils.e("串口打开成功");
                        JSONObject jsonObject = new JSONObject();
                        jsonObject.put("status", true);
                        jsonObject.put("msg", device.getName()+"打开成功");
                        callback.invoke(jsonObject);
                    }


                    @Override
                    public void onFail(final File device, final Status status) {
                        WXLogUtils.e("串口打开失败");
                        JSONObject jsonObject = new JSONObject();
                        switch (status){
                            case OPEN_FAIL:
                                jsonObject.put("status", false);
                                jsonObject.put("msg", device.getName()+"打开失败");
                                break;
                            case NO_READ_WRITE_PERMISSION:
                                jsonObject.put("status", false);
                                jsonObject.put("msg", "无权限");
                                break;
                        }
                        callback.invoke(jsonObject);
                    }
                });
                if(!helper.isOpen()){
                    helper.open();
                }
            }catch (Exception e){
                StringBuilder msg = new StringBuilder();
                //错误信息
                msg.append(" EXCEPTION: ").append("\n").append("PID: ").append(Process.myPid()).append("\n").append(e.getMessage()).append("\n");
                for(StackTraceElement element : e.getStackTrace()){
                    //错误类名-方法名-文件名:行数
                    msg.append("      at ").append(element.getClassName()).append(".").append(element.getMethodName()).append("(").append(element.getFileName()).append(":").append(element.getLineNumber()).append(")\n");
                }
                //记录到日志
                Log.e(TAG, msg.toString());
            }
        }

    }

    /**
     * 发送指令
     * @param option 参数
     * @param callback 回调
     */
    @JSMethod(uiThread = false)
    public void send(JSONObject option, JSCallback callback){
        Log.e(TAG, "进入send");
        mArray = new JSONArray();
        mArray = option.getJSONArray("sends");
        flag = 0;
        //回调对象
        JSONObject object = new JSONObject();
        //串口是否打开
        if(helper.isOpen()){
            //是否设置监听
            if(sendListener == null){
                object.put("status", false);
                object.put("msg", "请设置数据接收回调addListener");
                callback.invoke(object);
            }else{
                //是否设置命令
                if(mArray.size() == 0){
                    object.put("status", false);
                    object.put("msg", "串口指令不存在");
                    callback.invoke(object);
                }else{
                    helper.sendHex(mArray.getString(flag));
                    object.put("status", true);
                    object.put("msg", "发送成功");
                    callback.invoke(object);
                }
            }
        }else{
            object.put("status", false);
            object.put("msg", "串口未打开");
            callback.invoke(object);
        }
    }

    /**
     * 监听一次
     * @param callback 失败成功回调
     */
    @JSMethod(uiThread = false)
    public void addListener(final JSCallback callback){

        try{
            if(mWXSDKInstance.getContext() instanceof Activity){
                Log.e(TAG, "进入addListener");
                this.mCallback = callback;
                if(helper != null){
                    if(helper.isOpen()){
                        sendListener = new ISerialPortDataListener() {
                            @Override
                            public void onDataReceived(byte[] bytes, int size) {
                                WXLogUtils.e(ChangeTool.bytesToHexString(bytes));
                                JSONObject object = new JSONObject();
                                object.put("status", true);
                                object.put("bytes", bytes);
                                object.put("size", size);
                                mCallback.invoke(object);
                            }
                            @Override
                            public void onDataSend(byte[] bytes) {

                            }
                        };
                        helper.setISerialPortDataListener(sendListener);
                    }else{
                        JSONObject object = new JSONObject();
                        object.put("status", false);
                        object.put("msg", "串口未打开");
                        this.mCallback.invoke(object);
                    }
                }else{
                    JSONObject object = new JSONObject();
                    object.put("status", false);
                    object.put("msg", "串口未打开");
                    this.mCallback.invoke(object);
                }

            }
        }catch (Exception e){
            StringBuilder msg = new StringBuilder();
            //错误信息
            msg.append(" EXCEPTION: ").append("\n").append("PID: ").append(Process.myPid()).append("\n").append(e.getMessage()).append("\n");
            for(StackTraceElement element : e.getStackTrace()){
                //错误类名-方法名-文件名:行数
                msg.append("      at ").append(element.getClassName()).append(".").append(element.getMethodName()).append("(").append(element.getFileName()).append(":").append(element.getLineNumber()).append(")\n");
            }
            //记录到日志
            Log.e(TAG,"******************************CrashHandler******************************");
            Log.e(TAG, msg.toString());
            Log.e(TAG, "******************************CrashHandler******************************");
        }
    }

    /**
     * 持续监听
     * @param callback 发送状态回调
     */
    @JSMethod(uiThread = false)
    public void addListenerAndKeepAlive(final JSCallback callback){
        try{
            if(mWXSDKInstance.getContext() instanceof Activity){
                Log.e(TAG, "进入addListenerAndKeepAlive");
                this.mCallback = callback;
                if(helper != null){
                    if(helper.isOpen()){
                        sendListener = new ISerialPortDataListener() {
                            @Override
                            public void onDataReceived(byte[] bytes, int size) {
                                WXLogUtils.e(ChangeTool.bytesToHexString(bytes));
                                JSONObject object = new JSONObject();
                                object.put("status", true);
                                object.put("bytes", bytes);
                                object.put("size", size);

                                mCallback.invokeAndKeepAlive(object);
                                ++flag;
                                if(mArray != null){
                                    if(flag < mArray.size()){
                                        helper.sendHex(mArray.getString(flag));
                                    }
                                }
                            }
                            @Override
                            public void onDataSend(byte[] bytes) {

                            }
                        };
                        helper.setISerialPortDataListener(sendListener);
                    }else{
                        JSONObject object = new JSONObject();
                        object.put("status", false);
                        object.put("msg", "串口未打开");
                        this.mCallback.invoke(object);
                    }
                }else{
                    JSONObject object = new JSONObject();
                    object.put("status", false);
                    object.put("msg", "串口未打开");
                    this.mCallback.invoke(object);
                }
            }
        }catch (Exception e){
            StringBuilder msg = new StringBuilder();
            //错误信息
            msg.append(" EXCEPTION: ").append("\n").append("PID: ").append(Process.myPid()).append("\n").append(e.getMessage()).append("\n");
            for(StackTraceElement element : e.getStackTrace()){
                //错误类名-方法名-文件名:行数
                msg.append("      at ").append(element.getClassName()).append(".").append(element.getMethodName()).append("(").append(element.getFileName()).append(":").append(element.getLineNumber()).append(")\n");
            }
            //记录到日志
            Log.e(TAG,"******************************CrashHandler******************************");
            Log.e(TAG, msg.toString());
            Log.e(TAG, "******************************CrashHandler******************************");
        }
    }

    /**
     * 移除回调监听
     * @param callback 回调
     */
    @JSMethod(uiThread = false)
    public void removeListener(JSCallback callback){
        JSONObject object = new JSONObject();
        if(helper != null){
            helper.setISerialPortDataListener(null);
            object.put("status", true);
            object.put("msg", "删除成功");
            callback.invoke(object);
        }else{
            object.put("status", false);
            object.put("msg", "串口未打开");
            callback.invoke(object);
        }
    }

    @JSMethod(uiThread = false)
    public void getStatus(JSCallback callback){
        JSONObject object = new JSONObject();
        if(helper == null){
            object.put("status", false);
            object.put("msg", "请先初始化串口：调用open");
        }else{
            if(helper.isOpen()){
                object.put("msg", "串口已开启");
                object.put("status", helper.isOpen());
            }else{
                object.put("msg", "串口未开启");
                object.put("status", helper.isOpen());
            }

        }
        callback.invoke(object);
    }

    @JSMethod(uiThread = false)
    public void close(){
        destroy();
    }

    @Override
    public void destroy() {
        if(helper != null){
            helper.close();
        }
    }

    @JSMethod(uiThread = true)
    public void show(){
        Toast.makeText(mWXSDKInstance.getContext(), "test", Toast.LENGTH_LONG).show();
    }
}
